import time
import datetime
# import numpy as np
import io
import matplotlib.pyplot as plt
from PyQt5.QtWidgets import QApplication, QMainWindow
# from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import QTimer
from PIL import Image

from CapturePictureUI import Ui_MainWindow
from NetSDK.NetSDK import NetClient
from NetSDK.SDK_Enum import EM_LOGIN_SPAC_CAP_TYPE
from NetSDK.SDK_Struct import *
from NetSDK.SDK_Callback import fDisConnect, CB_FUNCTYPE

from predict34 import class_predict34
from materialLevelDetect import serverToClientMsg
import struct
import socket
import cv2
import multiprocessing as  mp
from multiprocessing import Process,Lock 
import threading

@CB_FUNCTYPE(None, C_LLONG, POINTER(c_ubyte), c_uint, c_uint, C_DWORD, C_LDWORD)
def CaptureCallBack(lLoginID,pBuf,RevLen,EncodeType,CmdSerial,dwUser):
    if lLoginID == 0:
        return
    # print('Enter CaptureCallBack')
    wnd.update_ui(pBuf, RevLen)
    
    
class CaptureWnd(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(CaptureWnd, self).__init__()
        self.setupUi(self)
        # 界面初始化
        self.init_ui()
        self.num = 1
        # 创建结构体对象并随机赋值
        self.msg = serverToClientMsg()
        self.msg.header = struct.pack('BB', 255, 7)
        self.msg.myData = struct.pack('BBBB', 7, 0, 0, 0)
        self.msg.setKind = [1, 1, 1, 1, 1]                 #各料库号
        self.msg.setBarn = [0 for _ in range(5)]    
        self.msg.kindSurplus = [10000 for _ in range(5)]    #对应料库物料剩余量
        self.msg.setChooseMission = 0
        self.HOST = '192.168.8.41'
        self.PORT = 8888
        self.flag = False
        # self.connect() # 1111
        self.count = 0
        self.start_time = time.time()
        self.all = 0

        # NetSDK用到的相关变量和回调
        self.loginID = C_LLONG()
        self.m_DisConnectCallBack = fDisConnect(self.DisConnectCallBack)

        # 获取NetSDK对象并初始化
        self.sdk = NetClient()
        self.sdk.InitEx(self.m_DisConnectCallBack)

    def init_ui(self):
        self.IP_lineEdit.setText('192.168.10.140')
        self.Port_lineEdit.setText('37777')
        self.User_lineEdit.setText('admin')
        self.Pwd_lineEdit.setText('@qwertyuiop159')
        self.Capture_pushButton.clicked.connect(self.capture_btn_onclick)
        self.Login_pushButton.setEnabled(True)
        self.Logout_pushButton.setEnabled(False)
        self.Capture_pushButton.setEnabled(False)

    def login_btn_onclick(self):

        ip = self.IP_lineEdit.text()
        port = int(self.Port_lineEdit.text())
        username = self.User_lineEdit.text()
        password = self.Pwd_lineEdit.text()
        stuInParam = NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY()
        stuInParam.dwSize = sizeof(NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY)
        stuInParam.szIP = ip.encode()
        stuInParam.nPort = port
        stuInParam.szUserName = username.encode()
        stuInParam.szPassword = password.encode()
        stuInParam.emSpecCap = EM_LOGIN_SPAC_CAP_TYPE.TCP
        stuInParam.pCapParam = None

        stuOutParam = NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY()
        stuOutParam.dwSize = sizeof(NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY)

        self.loginID, device_info, error_msg = self.sdk.LoginWithHighLevelSecurity(stuInParam, stuOutParam)
        if self.loginID != 0:
            self.setWindowTitle('(Capture)-(OnLine)')
            self.Login_pushButton.setEnabled(False)
            self.Logout_pushButton.setEnabled(True)
            if(int(device_info.nChanNum) > 0):
                self.Capture_pushButton.setEnabled(True)
            for i in range(int(device_info.nChanNum)):
                self.Channel_comboBox.addItem(str(i))

    # def start_timer(self):
    #     timer.start()

    def capture_btn_onclick(self,channel,cpu):
        # 设置抓图回调
        dwUser = 0
        print("capture_btn_onclick")
        self.sdk.SetSnapRevCallBack(CaptureCallBack, dwUser)
        # channel = self.Channel_comboBox.currentIndex()
        self.channel = 1
        # for channel in [0,2,3,4,5]:
            # print("channel:",channel)
        snap = SNAP_PARAMS()
        snap.Channel = channel
        snap.Quality = 1
        snap.mode = 0
        self.channel = channel
        self.num = cpu + 1
        # 抓图
        self.sdk.SnapPictureEx(self.loginID, snap)
        time.sleep(2)

    def connect(self):
        # always inline
        try:
            self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
            self.s.connect((self.HOST, self.PORT))
            self.flag = True
            print("connect_sucecss")
        except BaseException as e:
            self.flag = False
            print("connect_fail")

    def send_info(self):
        data = self.msg.pack()
        self.s.sendall(data)
        # print(f'Sent {len(data)} bytes: {data}')

    def update_ui(self, pBuf, RevLen):
        # global predicted
        self.count = self.count + 1
        class_pre34 = class_predict34()
        class_pre34.load_weight()
        self.pic_buf = cast(pBuf, POINTER(c_ubyte*RevLen)).contents
        # filename = f'frames/frame_{str(time.strftime("%S"))}.jpg'
        basename = '/media/nvidia/0e55e00d-e578-494d-8fca-279b1d6aceaf/WheelLoaderProgram_ws/yunnan_data/1217'
        # print("current_cpu:",self.num)
        filename = f'{basename}/{self.channel}/frames_{str(datetime.datetime.now().strftime("%Y%m%d-%H%M%S%f"))}.jpg'
        # filename = f'frame_{self.channel}/frame_{str(datetime.datetime.now().strftime("%Y%m%d-%H%M%S%f"))}.jpg'
        # with open(filename, 'wb+') as f:
        #     f.write(self.pic_buf)
        # print(filename)
        file_object = io.BytesIO(self.pic_buf)
        self.end_time = time.time()
        if (self.end_time - self.start_time>10):
            if(self.count != self.num):
                print("self.cunt ! = self.num",self.count,self.num)
                self.count = self.num
                self.all = self.all +1
                if(self.all > 5):
                    self.msg.setBarn[0] = self.error
        print("####################","self.count",self.count,"self.num",self.num)

        # # crop_box = (100,100,300,300)
        # # oringinal_image = Image.open(file_object)
        # # croped_image = oringinal_image.crop(crop_box)
        # # predict_result = class_pre34.predict34(croped_image)

        # # predict_result = class_pre34.predict34(filename)
        try:
            predict_result = class_pre34.predict34(file_object)
            # time.sleep(0.5)
            print(str(datetime.datetime.now().strftime("%Y%m%d-%H%M%S%f")))
            print("\nresnet34_predict_result:  ",predict_result,"object_Id:  ",self.num,"self.count  ",self.count,)
            print("self.channel:",self.channel)
            self.msg.setKind[self.num - 1] = self.num
            self.msg.kindSurplus[self.num - 1] = int(predict_result) * 2500
            # self.num = self.num + 1
        except BaseException as e:
            print(e)
        if(self.count == 2):
            self.count = 0



        # if (self.num == 5):
        #     print(self.msg.kindSurplus)
        #     # self.connect()
        #     self.num = 1

        # # image = QPixmap(filename).scaled(self.Picture_label.width(),
        # #                                                 self.Picture_label.height())
        # # self.Picture_label.setPixmap(image)
	
	# 实现断线回调函数功能
    def DisConnectCallBack(self):
        self.setWindowTitle("Capture-OffLine")

    def callback_img(self):
        while(1):
            for channel,cpu,error in zip([0,2],range(2),[3,1]): #   yunnan:   0,1,2,4,6
                print("currengt_channel:",channel)
                self.error = error
            # for channel in [5,4,3,2,0]: # True
                wnd.capture_btn_onclick(channel,cpu)

    # def callback_img(self):
    #     while(1):
            # arr = [0,1,2,4,6]
            # # arr = [6]
            # pool = mp.Pool(5)
            # results = []
            # for cpu,channel in zip(range(5),arr):
            #     # print(cpu,channel)
            #     result = pool.apply_async(wnd.capture_btn_onclick(channel,cpu),())
            #     time.sleep(1)
            #     results.append(result)
            # results = [r for r in results]
            # pool.close()
            # pool.join()


    # 关闭主窗口时清理资源
    def closeEvent(self, event):
        event.accept()
        if self.loginID:
            self.sdk.Logout(self.loginID)
            self.loginID = 0
        self.sdk.Cleanup()
        self.Picture_label.clear()
    
    def thread1_function(self):
        while True:
            try:
                print("setbarn:---------------",self.msg.setBarn)
                self.send_info()
            except BaseException as e:
                flag = False
            time.sleep(3)
 
if __name__ == '__main__':

    app = QApplication([])
    wnd = CaptureWnd()

    thread1 = threading.Thread(target=wnd.thread1_function)
    thread1.start()

    wnd.login_btn_onclick()
    # # wnd.show()

    wnd.callback_img()
    thread1.join()
    app.exec_()
